<?php

namespace App\Services;

use OpenTelemetry\API\Common\Instrumentation\Globals;
use OpenTelemetry\API\Trace\SpanInterface;
use OpenTelemetry\API\Trace\StatusCode;
use OpenTelemetry\API\Trace\TracerInterface;
use OpenTelemetry\API\Trace\TracerProviderInterface;
use OpenTelemetry\SDK\SdkAutoloader;
use OpenTelemetry\SDK\Trace\Span;

class TracerService
{

    public const Name = 'longmao';
    public static array $carrier = [];

    /**
     * tracer
     *
     * @return TracerInterface
     */
    public static function instance(): TracerInterface
    {
        static $instance;
        return $instance ??= self::provider()->getTracer(self::Name);
    }


    /**
     * provider
     *
     * @return TracerProviderInterface
     */
    public static function provider(): TracerProviderInterface
    {
        static $provider;
        static $sdkAutoLoad;
        if (! $sdkAutoLoad ) {
            SdkAutoloader::shutdown();
            SdkAutoloader::autoload();
            $sdkAutoLoad = true;
        }
        return $provider ??= Globals::tracerProvider();
    }

    /**
     * 关闭
     *
     * @return void
     */
    public static function shutdown()
    {
        self::provider()->shutdown();
    }

    /**
     * 强制输出
     *
     * @return bool
     */
    public static function forceFlush(): bool
    {
        return self::provider()->forceFlush();
    }

    /**
     * 记录事件
     *
     * @param string $name
     * @param iterable $attributes
     * @param int|null $timestamp
     * @return SpanInterface
     */
    public static function event(string $name, iterable $attributes = [], int $timestamp = null): SpanInterface
    {
        return Span::getCurrent()->addEvent($name, $attributes, $timestamp);
    }

    /**
     * 记录异常
     *
     * @param $exception
     * @param array $attr
     * @return SpanInterface
     */
    public static function recordException($exception, array $attr = []): SpanInterface
    {
        Span::getCurrent()->setStatus(StatusCode::STATUS_ERROR);
        return Span::getCurrent()->recordException($exception, $attr);
    }
}
